{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# -*- coding:utf-8 -*-\n",
    "% matplotlib inline\n",
    "from __future__ import print_function\n",
    "from matplotlib import pyplot as plt\n",
    "import matplotlib.pylab as pylab\n",
    "import os\n",
    "import cv2\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "MAX_FEATURES = 500\n",
    "GOOD_MATCH_PERCENT = 0.15\n",
    "\n",
    "def alignImages(im1, im2):\n",
    " \n",
    "  # Convert images to grayscale\n",
    "  im1Gray = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)\n",
    "  im2Gray = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)\n",
    "   \n",
    "  # Detect ORB features and compute descriptors.\n",
    "  orb = cv2.ORB_create(MAX_FEATURES)\n",
    "  keypoints1, descriptors1 = orb.detectAndCompute(im1Gray, None)\n",
    "  keypoints2, descriptors2 = orb.detectAndCompute(im2Gray, None)\n",
    "   \n",
    "  # Match features.\n",
    "  matcher = cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING)\n",
    "  matches = matcher.match(descriptors1, descriptors2, None)\n",
    "   \n",
    "  # Sort matches by score\n",
    "  matches.sort(key=lambda x: x.distance, reverse=False)\n",
    " \n",
    "  # Remove not so good matches\n",
    "  numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT)\n",
    "  matches = matches[:numGoodMatches]\n",
    " \n",
    "  # Draw top matches\n",
    "  imMatches = cv2.drawMatches(im1, keypoints1, im2, keypoints2, matches, None)\n",
    "  cv2.imwrite(\"matches.jpg\", imMatches)\n",
    "   \n",
    "  # Extract location of good matches\n",
    "  points1 = np.zeros((len(matches), 2), dtype=np.float32)\n",
    "  points2 = np.zeros((len(matches), 2), dtype=np.float32)\n",
    " \n",
    "  for i, match in enumerate(matches):\n",
    "    points1[i, :] = keypoints1[match.queryIdx].pt\n",
    "    points2[i, :] = keypoints2[match.trainIdx].pt\n",
    "   \n",
    "  # Find homography\n",
    "  h, mask = cv2.findHomography(points1, points2, cv2.RANSAC)\n",
    " \n",
    "  # Use homography\n",
    "  height, width, channels = im2.shape\n",
    "  im1Reg = cv2.warpPerspective(im1, h, (width, height))\n",
    "   \n",
    "  return im1Reg, h"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Read reference image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "refFilename = \"./pictures/anchor.jpg\"\n",
    "print(\"Reading reference image : \", refFilename)\n",
    "imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR)\n",
    "plt.imshow(imReference)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Read image to be aligned"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "imFilename = \"./pictures/target.jpg\"\n",
    "print(\"Reading image to align : \", imFilename);  \n",
    "im = cv2.imread(imFilename, cv2.IMREAD_COLOR)\n",
    "plt.imshow(im)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Registered image will be resotred in imReg."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "print(\"Aligning images ...\") \n",
    "# The estimated homography will be stored in h. \n",
    "imReg, h = alignImages(im, imReference)\n",
    "plt.imshow(imReg)\n",
    "plt.show()\n",
    "\n",
    "# Write aligned image to disk. \n",
    "print(\"Saving aligned image : \", \"./pictures/aligned.jpg\"); \n",
    "cv2.imwrite(\"./pictures/aligned.jpg\", imReg)\n",
    "\n",
    "# Print estimated homography\n",
    "print(\"Estimated homography : \\n\",  h)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SIF图像配准"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def sift_kp(image):\n",
    "    gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)\n",
    "    sift=cv2.xfeatures2d.SIFT_create()\n",
    "    kp,des = sift.detectAndCompute(image,None)\n",
    "    kp_image = cv2.drawKeypoints(gray_image,kp,None)\n",
    "    return kp_image,kp,des"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def get_good_match(des1,des2):\n",
    "    bf = cv2.BFMatcher()\n",
    "    matches = bf.knnMatch(des1, des2, k=2) #des1为模板图，des2为匹配图\n",
    "    matches = sorted(matches,key=lambda x:x[0].distance/x[1].distance)\n",
    "    good = []\n",
    "    for m, n in matches:\n",
    "        if m.distance < 0.75 * n.distance:\n",
    "            good.append(m)\n",
    "    return good"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def siftImageAlignment(img1,img2):\n",
    "   _,kp1,des1 = sift_kp(img1)\n",
    "   _,kp2,des2 = sift_kp(img2)\n",
    "   goodMatch = get_good_match(des1,des2)\n",
    "   if len(goodMatch) > 4:\n",
    "       ptsA= np.float32([kp1[m.queryIdx].pt for m in goodMatch]).reshape(-1, 1, 2)\n",
    "       ptsB = np.float32([kp2[m.trainIdx].pt for m in goodMatch]).reshape(-1, 1, 2)\n",
    "       ransacReprojThreshold = 4\n",
    "       H, status =cv2.findHomography(ptsA,ptsB,cv2.RANSAC,ransacReprojThreshold);\n",
    "       imgOut = cv2.warpPerspective(img2, H, (img1.shape[1],img1.shape[0]),flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)\n",
    "   return imgOut,H,status"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 配准"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# img1 = cv2.imread(r\"./pictures/anchor.jpg\")\n",
    "# img2 = cv2.imread(r\"./pictures/target.jpg\")\n",
    " \n",
    "# _,kp1,des1 = sift_kp(img1)\n",
    "# _,kp2,des2 = sift_kp(img2)\n",
    "# goodMatch = get_good_match(des1,des2)\n",
    " \n",
    "# img3 = cv2.drawMatches(img1, kp1, img2, kp2, goodMatch[:5], None, flags=2)\n",
    "# #----or----\n",
    "# #goodMatch = np.expand_dims(goodMatch,1)\n",
    "# #img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, goodMatch[:5], None, flags=2)\n",
    " \n",
    "# plt.imshow('img',img3)\n",
    "# cv2.waitKey(0)\n",
    "# cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 形状匹配"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "#性状匹配\n",
    "img1 = cv2.imread(\"./pictures/anchor.jpg\")\n",
    "img2 = cv2.imread(\"./pictures/target.jpg\")\n",
    "\n",
    "gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)\n",
    "ret, thresh1 = cv2.threshold(gray1, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)\n",
    "plt.imshow(thresh1)\n",
    "plt.show()\n",
    "\n",
    "gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)\n",
    "ret, thresh2 = cv2.threshold(gray2, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)\n",
    "plt.imshow(thresh2)\n",
    "plt.show()\n",
    "\n",
    "copyImage1, contours1, hierarchy1 = cv2.findContours(thresh1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
    "copyImage2, contours2, hierarchy2 = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
    "cnt1 = contours1[0]\n",
    "\n",
    "cnt = contours2[0]\n",
    "#找到性状的重心\n",
    "M = cv2.moments(cnt)\n",
    "cx = int(M['m10']/M['m00'])\n",
    "cy = int(M['m01']/M['m00'])\n",
    "print(cx, cy)\n",
    "cv2.circle(img2, (cx, cy), 5, (255,255,255), -1)\n",
    "#性状匹配\n",
    "ret = cv2.matchShapes(cnt1, cnt, 1, 0.0)\n",
    "print(ret)\n",
    "plt.imshow(gray2)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 阈值分割"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def segmentation(path):\n",
    "    files = os.listdir(path)\n",
    "    for name in files:\n",
    "        img_name = os.path.join(path, name)\n",
    "        img = cv2.imread(img_name)\n",
    "        \n",
    "        gray1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n",
    "        ret, thresh1 = cv2.threshold(gray1, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)\n",
    "        plt.imshow(thresh1, plt.cm.gray)\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "segmentation(\"./pictures/\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 图像去燥+阈值分割"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "img = cv2.imread(\"./pictures/anchor.jpg\")\n",
    "# BGR -> RGB\n",
    "img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)\n",
    "# Denoising\n",
    "dst = cv2.fastNlMeansDenoisingColored(img, None,10,10,7,21)\n",
    "plt.subplot(221), plt.imshow(img)\n",
    "plt.subplot(222), plt.imshow(dst)\n",
    "\n",
    "# Gray\n",
    "gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)\n",
    "plt.subplot(223), plt.imshow(gray, plt.cm.gray)\n",
    "\n",
    "# Bin\n",
    "ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)\n",
    "plt.subplot(224), plt.imshow(thresh, plt.cm.gray)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
